fix(#956): gate the pre-commit fallback on a 300s floor - #957
fix(#956): gate the pre-commit fallback on a 300s floor#957fullsend-ai-coder[bot] wants to merge 1 commit into
Conversation
|
🤖 Finished Review · ✅ Success · Started 1:18 AM UTC · Completed 1:36 AM UTC Commit: |
ReviewFindingsMedium
Low
Previous runReviewFindingsMedium
Low
Previous run (2)ReviewFindingsMedium
Low
Previous run (3)ReviewFindingsMedium
Previous run (4)ReviewFindingsMedium
Low
|
52d2080 to
c094b5e
Compare
|
🤖 Finished Review · ✅ Success · Started 1:44 PM UTC · Completed 1:58 PM UTC Commit: |
c094b5e to
9268f08
Compare
|
🤖 Review · Commit: |
9268f08 to
d1d9dbb
Compare
|
🤖 Review · Commit: |
d1d9dbb to
06929d3
Compare
|
🤖 Finished Review · ✅ Success · Started 2:32 PM UTC · Completed 2:49 PM UTC Commit: |
06929d3 to
7f288fb
Compare
|
🤖 Finished Review · ✅ Success · Started 2:52 PM UTC · Completed 3:10 PM UTC Commit: |
The direct-execution fallback in step 9b STEP C (introduced by #946) installs each hook's tool via pip and runs the hooks one at a time. The 10% gate that admits an agent into 9b was sized for the fast path -- a plain `pre-commit run` on a few files -- so an agent can clear it, hit an infrastructure failure, and enter the expensive path with too little budget left to finish it. Timing out mid-install produces no commit at all, which is worse than committing with the hooks disclosed as unrun. Re-check the budget at the point the fallback is entered, against a flat 300s floor. The floor is absolute rather than a fraction because what it guards costs about the same whatever the budget is; scaling it would only over-skip on the larger budget, and 300s clears the 150-250s window #956 identifies on both harnesses. Below the floor, set RUN_FALLBACK=0, skip the fallback substeps, and go to 9c with the skip disclosed. The fast path keeps its 10% gate. The check guards AGENT_START as well as TIMEOUT_SECONDS: unset, it evaluates as 0, which would put every run below the floor and turn the gate into a silent always-skip. It prints on every branch so the proceed path is not signalled by an empty result. Reconcile the surrounding text, which previously described a world with only two ways to stop short of pre-commit: 9b's lead, the threshold rationale, RULE 1's run accounting, and 9c's prohibition on re-entering 9b, whose stated reason ("you already used your 2 runs") was false on the skip path. State the run budget as per-iteration rather than per-sandbox: since #960 the validation loop treats pre-commit-blocked as agent-fixable and dispatches a retry that R6 tells to run pre-commit, so a session-wide lockout would block the retry that exists to fix it. Carry the same check into the fix-review skill inline rather than by cross-reference. harness/fix.yaml mounts only skills/fix-review, so the fix agent cannot read the code-implementation text its step 7b points at -- and fix-review is the agent this issue was filed about. Closes #956 Assisted-by: Claude (fix, review), Grok (review)
7f288fb to
363a7fc
Compare
|
🤖 Finished Review · ✅ Success · Started 3:14 PM UTC · Completed 3:30 PM UTC Commit: |
waynesun09
left a comment
There was a problem hiding this comment.
Approving as code owner (@fullsend-ai/core).
Reviewed across three multi-model rounds plus four bot rounds; head 363a7fc is 14/14 green. All remaining bot findings are LOW and either fixed in 363a7fc or documented in-file as deliberate (the flat 300s floor vs the 20% retry floors; the per-iteration budget rescoping required so #960's pre-commit-blocked retry is not locked out of step 9b/7b).
Summary
Step 9b's
STEP Cdirect-execution fallback (added by #946) is the expensive path: itpip installs each hook's tool at its pinnedrevand runs the hooks one at a time. The 10% time gate that admits an agent into 9b was sized for the fast path — a plainpre-commit runover a few changed files. So an agent can clear the 10% gate, hit an infrastructure failure in STEP B, and enter the expensive fallback with too little budget left to finish it. Timing out mid-pip installproduces no commit at all, which is worse than committing with the hooks disclosed as unrun.This adds a second, stricter recheck at the point the fallback is entered, and reconciles the surrounding text that assumed only two ways to stop short of pre-commit.
The floor is 300s, flat
Issue #956 puts the risky window at roughly 150–250s remaining.
harness/fix.yamlsetsTIMEOUT_SECONDS: 1500andharness/code.yamlsets2100, so their 10% gates are 150s and 210s. A 300s floor sits above the window on both.It is deliberately absolute rather than a fraction. What the floor guards costs about the same regardless of budget — it depends on how many remote hooks there are and what their
additional_dependenciespull in, not onTIMEOUT_SECONDS. A 20% fraction would put the code agent's floor at 420s and skip the fallback across a 210s-wide band it can comfortably afford, reintroducing the over-skipping that #956 says condemned the old 40% gate — and it would keep growing ifTIMEOUT_SECONDSwere ever raised.One consequence, stated in the code so it reads as a decision rather than an oversight: 300s can sit below 9c's uncapped 20% test-retry floor on the larger budget. That is intended — retrying tests is optional, running the fallback when there is time is the point.
Changes
skills/code-implementation/SKILL.mdRUN_FALLBACKcheck, with prose naming exactly which substeps to skip and the disclosure to write. GuardsAGENT_STARTalongsideTIMEOUT_SECONDS— unset, it evaluates as0, which would put every run below the floor and turn the gate into a silent always-skip. Prints on every branch, so "proceed" is never signalled by an empty result.RULE 1/ 9c: the run budget is now stated as per iteration, not per sandbox. Since feat(#949): run pre-commit inside the code/fix validation loop #960 the validation loop classifiespre-commit-blockedas agent-fixable and dispatches a retry into the same sandbox, andR6tells that retry to run pre-commit — so a session-wide lockout would have blocked the retry that exists to fix exactly this failure. 9c's own internal retries are still barred from re-entering 9b.skills/fix-review/SKILL.mdharness/fix.yamlmounts onlyskills/fix-review, so the fix agent cannot read the code-implementation text its 7b cross-reference points at — and fix-review is the agent fix-review can start step 7b too late to finish the STEP C direct-execution fallback #956 was filed about, with the smaller absolute margin.Testing
set -euo pipefailacross five scenarios each: 100s and 250s remaining →RUN_FALLBACK=0+::warning::; 400s and 2000s remaining →RUN_FALLBACK=1+::notice::;AGENT_STARTunset → no floor applied,RUN_FALLBACK=1+::notice::. Both files produce identical output on every case. NegativeREMAININGcorrectly trips the skip.make check-bundlepasses (exit 0)main; the earlier conflict on thefix-reviewthreshold line (< 40%→< 10%, from Fix-review skill pre-commit gate is too conservative, causing avoidable post-script failures #933) is resolved in favor of main's valueKnown limitation
Below the floor the skip is all-or-nothing — it drops
repo: localhooks along with the remote ones. That is deliberate and noted in both files: a localentrycan fetch on its own (uvx,pip), so it is not reliably the cheap case, and 9c/7c's mandatory lint run still happens below the floor. Carving out on-PATH local hooks would be a reasonable follow-up.Closes #956